`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2021/08/05 14:26:38
// Design Name: 
// Module Name: FeatureOutBufferTest
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module FeatureOutBufferTest;
parameter DATA_WIDTH = 32;
parameter ADDR_WIDTH = 32;
parameter DEPTH = 32;
parameter BANK = 4;
//
logic clk;
logic rst;
//single write
logic single_we;
logic [ADDR_WIDTH-1:0] single_wr_addr;
logic [DATA_WIDTH-1:0] single_wr_data;
//multi write
logic multi_we;
logic [ADDR_WIDTH-1:0] wr_addr;
logic [DATA_WIDTH-1:0] wr_data [0:BANK-1];
//read
logic [ADDR_WIDTH-1:0] rd_addr;
logic [DATA_WIDTH-1:0] rd_data [0:BANK-1];
//单端口写
logic start_single_write;
logic single_writing;
logic single_write_done;
//多端口写
logic start_multi_write;
logic multi_writing;
logic multi_write_done;
//多端口读
logic start_read;
logic reading;
logic read_done;
//
//clk
initial begin
    clk=1;
    forever begin
        #5 clk=~clk;
    end
end
//rst
initial begin
    rst=1;
    #20
    rst=0;
end
//start_single_write
initial begin
    start_single_write=0;
    #100
    start_single_write=1;
    #10
    start_single_write=0;
end
//start_multi_write
initial begin
    start_multi_write=0;
    // #100
    // start_multi_write=1;
    // #10
    // start_multi_write=0;
end
//single_writing
always_ff@(posedge clk,posedge rst)
if(rst)
    single_writing<=0;
else if(start_single_write)
    single_writing<=1;
else if(single_wr_addr==BANK*DEPTH-1)
    single_writing<=0;
//multi_writing
always_ff@(posedge clk,posedge rst)
if(rst)
    multi_writing<=0;
else if(start_multi_write)
    multi_writing<=1;
else if(wr_addr==DEPTH-1)
    multi_writing<=0;
//single_we
assign single_we=single_writing;
//multi_we
assign multi_we=multi_writing;
//single_wr_data
assign single_wr_data=single_wr_addr;
//wr_data
always_comb
begin
for(int i=0;i<BANK;i++)
    wr_data[i]=wr_addr+DEPTH*i;
end
//single_wr_addr
always_ff@(posedge clk)
if(start_single_write)
    single_wr_addr<=0;
else if(single_writing)
    single_wr_addr<=single_wr_addr+1;
//multi_wr_addr
always_ff@(posedge clk)
if(start_multi_write)
     wr_addr<=0;
else if(multi_writing)
     wr_addr<=wr_addr+1;
//single_write_done
assign single_write_done=(single_wr_addr==BANK*DEPTH-1)?1:0;
//multi_write_done
assign multi_write_done=(wr_addr==DEPTH-1)?1:0;
//read_start
always_ff@(posedge clk,posedge rst)
if(rst)
    start_read<=0;
else if(multi_write_done||single_write_done)
    start_read<=1;
else
    start_read<=0;
//reading
always_ff@(posedge clk,posedge rst)
if(rst)
    reading<=0;
else if(start_read)
    reading<=1;
else if(rd_addr==DEPTH-1)
    reading<=0;
//rd_addr
always_ff@(posedge clk,posedge rst)
if(rst)
    rd_addr<=0;
else if(start_read)
    rd_addr<=0;
else if(reading)
    rd_addr<=rd_addr+1;
/*******************************************************/
//例化
FeatureOutBuffer
#(.ADDR_WIDTH(ADDR_WIDTH),
  .DATA_WIDTH(DATA_WIDTH),
  .BANK(BANK),
  .DEPTH(DEPTH))
U (
.clk(clk),
.rst(rst),
//单端口写入
.single_wr_addr(single_wr_addr),
.single_wr_data(single_wr_data),
.single_we(single_we),
//多端口写入                                                //单端口写入和多端口写入不能同时使用
.wr_addr(wr_addr),
.wr_data(wr_data),
.multi_we(multi_we),
//多端口读出
.rd_addr(rd_addr),
.rd_data(rd_data)
    );
endmodule
